﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using YiDa.Domain.Specifications;

namespace YiDa.Domain.Test
{
    /// <summary>
    /// 测试规约及各种组件
    /// </summary>
    [TestClass]
    public class SpecificationTest
    {
        private List<TestEntity> list = null;

        [TestInitialize()]
        public void Initialize()
        {
            list = new List<TestEntity>();
            list.AddRange(new [] { 
                    new TestEntity{Id=1,Name="A"},
                    new TestEntity{Id=2,Name="B"},
                    new TestEntity{Id=3,Name="C"},
                    new TestEntity{Id=4,Name="D"},
                    new TestEntity{Id=5,Name="E"},
                    new TestEntity{Id=6,Name="F"},
                    new TestEntity{Id=7,Name="G"},
                    new TestEntity{Id=8,Name="H"},
                    new TestEntity{Id=9,Name="I"},
                }
            );
        }

        [TestMethod]
        public void TestNotSpecification()
        {
            var ex = Specification<TestEntity>.Eval(t => t.Id == 1).Not();            
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(list.Count()-1, r.Count());            
        }

        [TestMethod]
        public void TestNoneSpecification()
        {
            var ex = new NoneSpecification<TestEntity>();
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(0, r.Count());
        }

        [TestMethod]
        public void TestExpressionSpecification()
        {
            var ex = Specification<TestEntity>.Eval(t => t.Id == 1);
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(1, r.Count());
            r.ToList()[0] = list[0];
        }

        [TestMethod]
        public void TestAnySpecification()
        {
            var ex = new AnySpecification<TestEntity>();
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(list.Count(), r.Count());
        }

        [TestMethod]
        public void TestOrSpecification()
        {
            var ex = Specification<TestEntity>.Eval(t => t.Id == 1).Or(Specification<TestEntity>.Eval(t => t.Id == 2));
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(2, r.Count());            
        }

        [TestMethod]
        public void TestAndSpecification()
        {
            var ex = Specification<TestEntity>.Eval(t => t.Id > 1).And(Specification<TestEntity>.Eval(t => t.Id < 4));
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(2, r.Count());
        }

        [TestMethod]
        public void TestAndNotSpecification()
        {
            var ex = Specification<TestEntity>.Eval(t => t.Id > 1).AndNot(Specification<TestEntity>.Eval(t => t.Id > 4));
            var r = list.Where(ex.IsSatisfiedBy);
            Assert.AreEqual(3, r.Count());              //不大于4，则有2,3,4
        }
    }

    public class TestEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}
